bitkeeper revision 1.1223 (4215eee4gqIO-1mu8V6FHhIhoaqaiQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 18 Feb 2005 13:34:28 +0000 (13:34 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 18 Feb 2005 13:34:28 +0000 (13:34 +0000)
Change priv-op emulation behaviour to fail silently in some cases
rather than propagate the fault (still non-silent in debug builds!).
Also be careful in running user-specified RDMSR/WRMSR: an invalid
MSR index causes a GP(0) fault.
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/dom0_ops.c
xen/arch/x86/traps.c
xen/include/asm-x86/config.h
xen/include/asm-x86/msr.h

index 0f455c6800f1854089c1b59d7898fc4ee81e7204..3c11c8af6def2d16ef838cf8cb3e7bb66349984f 100644 (file)
@@ -36,13 +36,13 @@ static unsigned long msr_hi;
 static void write_msr_for(void *unused)
 {
     if (((1 << current->processor) & msr_cpu_mask))
-        wrmsr(msr_addr, msr_lo, msr_hi);
+        (void)wrmsr_user(msr_addr, msr_lo, msr_hi);
 }
 
 static void read_msr_for(void *unused)
 {
     if (((1 << current->processor) & msr_cpu_mask))
-        rdmsr(msr_addr, msr_lo, msr_hi);
+        (void)rdmsr_user(msr_addr, msr_lo, msr_hi);
 }
 
 long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
index 36280de46c06ac35241cf9e66c2e450e6ae70b4a..a2ac58ad0ce5fc148f00ffe1eaa0cc1d9094df80 100644 (file)
@@ -375,12 +375,11 @@ static int emulate_privileged_op(struct xen_regs *regs)
         break;
 
     case 0x09: /* WBINVD */
+        /* Ignore the instruction if unprivileged. */
         if ( !IS_CAPABLE_PHYSDEV(ed->domain) )
-        {
             DPRINTK("Non-physdev domain attempted WBINVD.\n");
-            goto fail;
-        }
-        wbinvd();
+        else
+            wbinvd();
         break;
 
     case 0x20: /* MOV CR?,<reg> */
@@ -441,21 +440,21 @@ static int emulate_privileged_op(struct xen_regs *regs)
         break;
 
     case 0x30: /* WRMSR */
+        /* Ignore the instruction if unprivileged. */
         if ( !IS_PRIV(ed->domain) )
-        {
-            DPRINTK("Non-priv domain attempted WRMSR.\n");
+            DPRINTK("Non-priv domain attempted WRMSR(%p,%08lx,%08lx).\n",
+                    regs->ecx, (long)regs->eax, (long)regs->edx);
+        else if ( wrmsr_user(regs->ecx, regs->eax, regs->edx) )
             goto fail;
-        }
-        wrmsr(regs->ecx, regs->eax, regs->edx);
         break;
 
     case 0x32: /* RDMSR */
         if ( !IS_PRIV(ed->domain) )
-        {
-            DPRINTK("Non-priv domain attempted RDMSR.\n");
+            DPRINTK("Non-priv domain attempted RDMSR(%p,%08lx,%08lx).\n",
+                    regs->ecx, (long)regs->eax, (long)regs->edx);
+        /* Everyone can read the MSR space. */
+        if ( rdmsr_user(regs->ecx, regs->eax, regs->edx) )
             goto fail;
-        }
-        rdmsr(regs->ecx, regs->eax, regs->edx);
         break;
 
     default:
index 787d9536916797b8e5004a20d537883d4a1e598d..84a0492e1d55a977cd7066949ac9b9d19cd9b98b 100644 (file)
@@ -206,8 +206,10 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn));
 #define __GUEST_SS        0x082b
 
 /* For generic assembly code: use macros to define operation/operand sizes. */
-#define __OS "q"  /* Operation Suffix */
-#define __OP "r"  /* Operand Prefix */
+#define __OS          "q"  /* Operation Suffix */
+#define __OP          "r"  /* Operand Prefix */
+#define __FIXUP_ALIGN ".align 8"
+#define __FIXUP_WORD  ".quad"
 
 #elif defined(__i386__)
 
@@ -264,8 +266,10 @@ extern void __out_of_line_bug(int line) __attribute__((noreturn));
 #define __HYPERVISOR_DS 0x0810
 
 /* For generic assembly code: use macros to define operation/operand sizes. */
-#define __OS "l"  /* Operation Suffix */
-#define __OP "e"  /* Operand Prefix */
+#define __OS          "l"  /* Operation Suffix */
+#define __OP          "e"  /* Operand Prefix */
+#define __FIXUP_ALIGN ".align 4"
+#define __FIXUP_WORD  ".long"
 
 #endif /* __i386__ */
 
index a7178f2e3b5e5e45bd828f1338640e7d39f2dc11..dd01e9642a0485f8cd77db0eae3673d7c150233f 100644 (file)
@@ -1,29 +1,46 @@
 #ifndef __ASM_MSR_H
 #define __ASM_MSR_H
 
-/*
- * Access to machine-specific registers (available on 586 and better only)
- * Note: the rd* operations modify the parameters directly (without using
- * pointer indirection), this allows gcc to optimize better
- */
-
 #define rdmsr(msr,val1,val2) \
      __asm__ __volatile__("rdmsr" \
                          : "=a" (val1), "=d" (val2) \
                          : "c" (msr))
 
-#define rdmsrl(msr,val) do { unsigned long a__,b__; \
-       __asm__ __volatile__("rdmsr" \
-                           : "=a" (a__), "=d" (b__) \
-                           : "c" (msr)); \
-       val = a__ | (b__<<32); \
-} while(0); 
-
 #define wrmsr(msr,val1,val2) \
      __asm__ __volatile__("wrmsr" \
                          : /* no outputs */ \
                          : "c" (msr), "a" (val1), "d" (val2))
 
+#define rdmsr_user(msr,val1,val2) ({\
+    int _rc = 0; \
+    __asm__ __volatile__( \
+        "1: rdmsr\n2:\n" \
+        ".section .fixup,\"ax\"\n" \
+        "3: movl $1,%2\n; jmp 2b\n" \
+        ".previous\n" \
+        ".section __ex_table,\"a\"\n" \
+        "   "__FIXUP_ALIGN"\n" \
+        "   "__FIXUP_WORD" 1b,3b\n" \
+        ".previous\n" \
+        : "=a" (val1), "=d" (val2), "=r" (_rc) \
+        : "c" (msr)); \
+    _rc; })
+
+#define wrmsr_user(msr,val1,val2) ({\
+    int _rc = 0; \
+    __asm__ __volatile__( \
+        "1: wrmsr\n2:\n" \
+        ".section .fixup,\"ax\"\n" \
+        "3: movl $1,%0\n; jmp 2b\n" \
+        ".previous\n" \
+        ".section __ex_table,\"a\"\n" \
+        "   "__FIXUP_ALIGN"\n" \
+        "   "__FIXUP_WORD" 1b,3b\n" \
+        ".previous\n" \
+        : "=r" (_rc) \
+        : "c" (msr), "a" (val1), "d" (val2)); \
+    _rc; })
+
 #define rdtsc(low,high) \
      __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))